#include "list_base.h"
// std-lib
#include <stdlib.h>

/*-----------------------------------------------APP----------------------------------------------------*/

#if 0 // 用于测试
/// @brief 比较函数
/// @param a 比较数据1
/// @param b 比较数据2
/// @return 比较结果
int list_node_compare(const void *a, const void *b)
{
    // return (*(SDPFLCE_t *)a).num - (*(SDPFLCE_t *)b).num;                               // 升序
    // return (*(SDPFLCE_t *)b).num - (*(SDPFLCE_t *)a).num;                               // 降序
}

void main(void)
{
#if 1
    //带顺序的链表，用List_Insert插入
    list_base_t ptListHead = {0};
    int a = 1;
    int b = 2;
    int c = 3;

    list_init(&ptListHead);
    list_insert(&ptListHead, &a,list_node_compare);
    list_insert(&ptListHead, &b,list_node_compare);
    list_insert(&ptListHead, &c,list_node_compare);
#else
    //不带顺序的链表，用List_Add插入
    list_base_t ptListHead = {0};
    int a = 1;
    int b = 2;
    int c = 3;

    list_init(&ptListHead);
    list_add(&ptListHead, &a);
    list_add(&ptListHead, &b);
    list_add(&ptListHead, &c);
#endif
}
#endif

/*-------------------------------------------------------------------------------------------------------*/
/// @brief 链表初始化
void list_init(list_base_t *ptListHead)
{
    if (ptListHead == NULL)
        return;
    if (ptListHead->iListLen != 0)
        return;
    ptListHead->ptHead.pData = NULL;
    ptListHead->ptHead.ptLast = &ptListHead->ptHead;
    ptListHead->ptHead.ptNext = &ptListHead->ptHead;
    ptListHead->iListLen = 0;
}

/// @brief 插入到第一个节点
/// @param ptListHead
/// @param pData
void list_add(list_base_t *ptListHead, void *pData)
{
    if (ptListHead == NULL || pData == NULL)
        return;

    // 新建节点
    list_node_t *node = (list_node_t *)LIST_HEAP_MALLOC(sizeof(list_node_t));
    node->pData = pData;

    // 插入第一个节点的位置
    node->ptLast = &ptListHead->ptHead;
    node->ptNext = ptListHead->ptHead.ptNext;

    node->ptLast->ptNext = node;
    node->ptNext->ptLast = node;

    ptListHead->iListLen++;
}

/// @brief 插入到最后一个节点
/// @note 用于不需要排序的链表
/// @param ptListHead
/// @param pData
void list_add_end(list_base_t *ptListHead, void *pData)
{
    if (ptListHead == NULL || pData == NULL)
        return;
    // 新建节点
    list_node_t *node = (list_node_t *)LIST_HEAP_MALLOC(sizeof(list_node_t));
    node->pData = pData;

    // 插入最后一个节点的位置
    node->ptLast = ptListHead->ptHead.ptLast;
    node->ptNext = &ptListHead->ptHead;

    node->ptLast->ptNext = node;
    node->ptNext->ptLast = node;

    ptListHead->iListLen++;
}

/// @brief 按顺序插入节点
/// @param ptListHead 链表头指针
/// @param pData 数据指针
/// @param fnCompare 比较函数
void list_insert(list_base_t *ptListHead, void *pData, fn_i32_pp fnCompare)
{
    if (ptListHead == NULL || pData == NULL || fnCompare == NULL)
        return;

    // 新建节点
    list_node_t *node = (list_node_t *)LIST_HEAP_MALLOC(sizeof(list_node_t));
    node->pData = pData;

    list_node_t *p = &ptListHead->ptHead;
    void *node_data_p;

    while (p->ptNext != &ptListHead->ptHead)
    {
        node_data_p = p->ptNext->pData;
        // 这里使用“<”和“<=”的含义不同
        if (node_data_p && fnCompare((const void *)pData, (const void *)node_data_p) < 0)
        {
            break;
        }

        p = p->ptNext;
    }

    node->ptLast = p;
    node->ptNext = p->ptNext;

    node->ptLast->ptNext = node;
    node->ptNext->ptLast = node;

    ptListHead->iListLen++;
}

/// @brief 查找指定节点并删除
/// @param ptListHead
/// @param pData
void list_delete_node(list_base_t *ptListHead, void *pData)
{
    if (ptListHead == NULL || pData == NULL)
        return;

    list_node_t *p = &ptListHead->ptHead;

    while (p->ptNext != &ptListHead->ptHead)
    {
        if (p->ptNext->pData != NULL && p->ptNext->pData == pData)
        {
            break;
        }

        p = p->ptNext;
    }

    if (p->ptNext == &ptListHead->ptHead)
    {
        // printf("未找到\n");
        return;
    }

    list_node_t *temp = p->ptNext;
    temp->ptLast->ptNext = temp->ptNext;
    temp->ptNext->ptLast = temp->ptLast;

    LIST_HEAP_FREE(temp);

    temp = NULL;

    ptListHead->iListLen--;
}

/// @brief 返回链表头部数据的同时删除头部节点
/// @param ptListHead
/// @return
void *list_pop(list_base_t *ptListHead)
{
    if (ptListHead == NULL)
        return NULL;
    if (ptListHead->ptHead.ptNext == &ptListHead->ptHead)
        return NULL;

    list_node_t *temp = ptListHead->ptHead.ptNext;
    void *pData = temp->pData;
    temp->ptLast->ptNext = temp->ptNext;
    temp->ptNext->ptLast = temp->ptLast;

    LIST_HEAP_FREE(temp);

    temp = NULL;

    return pData;
}

/// @brief 删除所有节点
/// @param ptListHead
void list_delete_all_node(list_base_t *ptListHead)
{
    if (ptListHead == NULL)
        return;
    list_node_t *p = ptListHead->ptHead.ptNext;
    list_node_t *temp;

    while (p != &ptListHead->ptHead)
    {
        temp = p;
        p = p->ptNext;

        temp->ptLast->ptNext = temp->ptNext;
        temp->ptNext->ptLast = temp->ptLast;

        LIST_HEAP_FREE(temp);

        temp = NULL;
    }

    ptListHead->iListLen = 0;
}

/// @brief 获取下一个节点
/// @param node
/// @return
list_node_t *list_get_next_node(list_node_t *node)
{
    if (node == NULL)
        return NULL;
    return node->ptNext;
}

/// @brief 按顺序获取节点数据
/// @param ptListHead
/// @param iNum
/// @return
void *list_get_node_by_num(list_base_t *ptListHead, uint32_t uNum)
{
    if (ptListHead == NULL)
        return NULL;
    if (uNum > ptListHead->iListLen)
        return NULL;

    list_node_t *p = ptListHead->ptHead.ptNext;

    while (p != &ptListHead->ptHead && uNum--)
    {
        p = p->ptNext;
        if (p == &ptListHead->ptHead)
        {
            return NULL;
        }
    }

    return p->pData;
}
